/*
 *  $Id: Language.cs 1181 2010-11-10 16:08:03Z thenn.erannor $
 *	This file is a part of Ragima CCG.
 *	(C) 2008-2010 Ragima development group.
 *
 *	Licensed under the terms of the GNU GPL License version 2.
 *
 */

using System;
using System.Collections.Generic;

using AgateLib.Resources;

using Nereal.Extensions;

namespace Ragima.Languages {
    /// <summary>
    /// Данные о каком-либо конкретном языке.
    /// </summary>
    public class Language {
        private static Language _current;

        /// <summary>
        /// Список всех загруженных языков.
        /// </summary>
        public static readonly LanguageList AllLanguages = new LanguageList();

        /// <summary>
        /// Текущий системный язык. Используется для выбора текущих ресурсов.
        /// </summary>
        public static Language CurrentLanguage {
            get { return _current; }
            set { _current = value; }
        }

        private string _code;
        private List<ILocalizer> _localizers;
        private Dictionary<Type, Type> _typeMap;
        private AgateResourceCollection _resources;

        public Language(string code) {
            _code = code;
            _localizers = new List<ILocalizer>();
            _typeMap = new Dictionary<Type, Type>();
        }

        /// <summary>
        /// Код языка, по которому он идентифируется.
        /// </summary>
        public string LangCode {
            get { return _code; }
        }

        /// <summary>
        /// Добавляет локализатор к данному языку.
        /// </summary>
        public void AddLocalizer(ILocalizer localizer) {
            _localizers.Add(localizer);
        }

        /// <summary>
        /// Добавляет локализованную версию типа.
        /// </summary>
        /// <param name="baseType">Базовый тип</param>
        /// <param name="locType">Локализованный тип</param>
        public void AddLocalizedType(Type baseType, Type locType) {
            if (!locType.IsSubclassOf(baseType))
                return;
            var attr = locType.GetAttribute<ResourceLangAttribute>();
            if (attr != null && attr.LangCode == LangCode)
                _typeMap.Add(baseType, locType);
        }

        /// <summary>
        /// Получает локализованную версию типа.
        /// </summary>
        /// <param name="baseType">Базовый тип</param>
        public Type GetLocalizedType(Type baseType) {
            return _typeMap.GetOrDefault(baseType, baseType);
        }

        /// <summary>
        /// Суммарное количество ресурсов всех локализаторов данного языка.
        /// </summary>
        public int ResourceCount {
            get {
                int count = 0;
                foreach (ILocalizer loc in _localizers)
                    count += loc.ResourceCount;
                return count;
            }
        }

        /// <summary>
        /// Ищет локализованную версию ресурса по идентификатору.
        /// </summary>
        public T FindResource<T>(string resourceId) where T : class, ILocalized {
            foreach (var loc in _localizers) {
                T resource = loc.FindResource<T>(resourceId);
                if (resource != null)
                    return resource;
            }
            return null;
        }

        /// <summary>
        /// Получает локализованный к данному языку ресурс, и привести его к указанному типу.
        /// </summary>
        public R GetResource<T, R>(ILocalizable<T> resource) where T: ILocalized where R: class, T {
            return resource.GetResource(this) as R;
        }

        /// <summary>
        /// Получает имя файла с информацией о шрифтах.
        /// </summary>
        public string GetFontsFileName() {
            return string.Format("{0}_fonts.xml", LangCode);
        }

        /// <summary>
        /// Получает идентификатор шрифта с учетом языка.
        /// </summary>
        public string GetFontId(string id) {
            return string.Format("{0}_font_{1}", LangCode, id);
        }

        /// <summary>
        /// Получает имя файла с информацией о ресурсах.
        /// </summary>
        public string GetResourcesFileName() {
            return string.Format("{0}_resources.xml", LangCode);
        }

        /// <summary>
        /// Получает коллекцию ресурсов.
        /// </summary>
        public AgateResourceCollection GetResources() {
            return _resources ?? (_resources = new AgateResourceCollection(GetResourcesFileName()));
        }

        /// <summary>
        /// Хэш языка равен хэшу его кода.
        /// </summary>
        public override int GetHashCode() {
            return LangCode.GetHashCode();
        }

        /// <summary>
        /// Язык в строковом виде представлен его кодом.
        /// </summary>
        public override string ToString() {
            return LangCode;
        }
    }
}
